/********************************************************************
* Name: X86AsmGenerator.h: 
*
* Description:
*   Generate Pseudo-x86-asm-code defined within 
*   X86Code abstract structure from IL representation. 
*   
*
* History:
*   Create: gxf. 2009-03-28
*
********************************************************************/
#ifndef X86_ASM_GENERATOR_H
#define X86_ASM_GENERATOR_H

#include "crossbit/VInst.h"
#include "crossbit/RegAllocator.h"

namespace crossbit{

class AsmBlock;
class TBlock;
class VInst;

//TODO: Pseudo instruction selector here
class InstSelector{} ;

class X86AsmGenerator{
    public:
        X86AsmGenerator(ProcessorState *state, RegAllocator *alloc):
            _state(state), _regAlloc(alloc)
        {}
        virtual ~X86AsmGenerator(){}

    protected:
        ProcessorState* _state;
        RegAllocator*   _regAlloc;
        InstSelector*   _instSelect;

    // Interface functions
    public:
        AsmBlock* GenPseudoAsm(VBlock * vblock);

        FINLINE void setRegAllocator(RegAllocator * allocator) {
            _regAlloc = allocator;
        }

    protected: 
        // Wrapper functions of register allocator. 
        // Since allocator may use ESP, the class should deal with it.  
        INLINE XTRegNum X86RegAlloc(XTRegNum vreg, RegAccessMode mode);

        INLINE XTRegNum X86RegAllocForce(XTRegNum vreg, XTRegNum expect, RegAccessMode mode);

        INLINE XTRegNum X86RegAllocExpect(XTRegNum vreg, XTUint8 reg_mask, RegAccessMode mode);

        INLINE XTRegNum X86RegAllocForceExcept(XTRegNum vreg, XTRegNum except, RegAccessMode mode);

        INLINE void X86RegAllocReserve(XTRegNum treg);

        INLINE void X86RegAllocRelease(XTRegNum treg);

    protected:
        void encodeGET();
        void encodePUT();
        void encodeLD();
        void encodeST();
        void encodeLI();
        void encodeLIRETURN();
        void encodeRETURN();
        void encodeMOV();
        void encodeSEXT();
        void encodeZEXT();
        void encodeADD();
        void encodeADDI();
        void encodeSUB();
        void encodeAND();
        void encodeXOR();
        void encodeOR();
        void encodeNOT();
        void encodeMUL();
        void encodeMULU();
        void encodeDIV();
        void encodeDIVU();
        void encodeSLL();
        void encodeSLLV();
        void encodeSRL();
        void encodeSRLV();
        void encodeSRA();
        void encodeSRAV();
        void encodeCMP();
        void encodeJMP();
        void encodeBRANCH();
        void encodeSYSCALL();
        void encodeHALT();
        void encodeSBREAK(); 
        // stack-based floating point
        void encodeFPUTS();
        void encodeFGETS();
        void encodeFPUTD();
        void encodeFGETD(); 
        void encodeFLD();
        void encodeFST();
        void encodeFMOV();

        void encodeFADDS();
        void encodeFADDD();
        void encodeFSUBS();
        void encodeFSUBD();
        void encodeFMULS();
        void encodeFMULD();
        void encodeFDIVS();
        void encodeFDIVD();
        void encodeFNEGS();
        void encodeFNEGD();
        void encodeFABSS();
        void encodeFABSD();
        void encodeFSQRTS();
        void encodeFSQRTD();
        void encodeFCMPS();
        void encodeFCMPD();

        void encodeFCONV();
        void encodeFINCSTP();
        void encodeCALL();

    protected:
        static void (*)() funcTab[OP_TATAL_INSTS];
};
} // crossbit

#endif

